<template>
  <div id="root">
    <div :class="cssClasses" v-if="AppIsInited">
      <component
        :is="$route.meta.layout"
        :title="title"
        :is-x-small="screen.getScreenSizeInfo.isXSmall"
        :is-large="screen.getScreenSizeInfo.isLarge"
      >
        <div class="content">
          <router-view
            v-on:showErrorDialog="showErrorDialog"
            v-on:showLoadingOfApp="showLoadingOfApp"
          ></router-view>
        </div>
        <template #footer>
          <app-footer />
        </template>
      </component>
    </div>
    <DxLoadPanel
      v-model:visible="loadPanelInfo.loadingVisible"
      :show-indicator="loadPanelInfo.showIndicator"
      :show-pane="loadPanelInfo.showPane"
      :shading="loadPanelInfo.shading"
      :close-on-outside-click="loadPanelInfo.closeOnOutsideClick"
      shading-color="rgba(0,0,0,0)"
      :width="90"
      :height="90"
    />
    <RightMenu
      v-model:items="rightContextOption.items"
      v-model:content="rightContextOption.content"
      :defaultRightContextOption="defaultRightContextOption"
    />
  </div>
</template>

<script lang="ts">
import AppFooter from "./components/app-footer.vue";
import { DxPopup } from "devextreme-vue/popup";
import { DxLoadPanel } from "devextreme-vue/load-panel";
import { sizes, subscribe, unsubscribe } from "./utils/media-query";
import { Options, Vue } from "vue-class-component";
import zhMessages from "devextreme/localization/messages/zh.json";
import { locale, loadMessages } from "devextreme/localization";
import { ApiTool } from "./api/api-tool";
import Menu from "./utils/menu";
import { Provide } from "vue-property-decorator";
import notify from "devextreme/ui/notify";
import { LOGINPATH } from "./utils/basic-data";
import ThemeSwitch from "./framework/theme-switch/theme-switch";
import { Auth } from "./utils/auth";
import { authClient, AuthInfoI } from "./api/api_auth";
import { ViewTool } from "./framework/utils/view-tool";
import RightMenu, {
  RightContextI,
} from "./framework/components/right-menu/right-menu.vue";
import DxContextMenu from "devextreme-vue/context-menu";
import config from "@/config/config";
const { authOptions } = config;

/** 加载框结构 */
interface DxLoadPanelInfo {
  /** 是否显示loading */
  loadingVisible: boolean;

  showIndicator: boolean;

  showPane: boolean;

  /**点loading框外部是否关闭它 */
  closeOnOutsideClick: boolean;
}

/** 错误框结构 */
interface DxDialogInfo {
  /**是否显示 */
  show: boolean;

  /**显示消息 */
  msg: string;
}

@Options({
  components: {
    AppFooter,
    DxPopup,
    DxLoadPanel,
    RightMenu,
    DxContextMenu,
  },
})
export default class AppRoot extends Vue {
  items = [
    {
      text: "刷新",
    },
  ];
  screen = {
    getScreenSizeInfo: this.getScreenSizeInfo(),
  };

  get title() {
    let that = this as any;
    return that.$appInfo.title;
  }

  get cssClasses() {
    return ["app"].concat(this.screen.getScreenSizeInfo.cssClasses);
  }

  /** 等待框加载信息 */
  loadPanelInfo: DxLoadPanelInfo = {
    showIndicator: true,
    showPane: true,
    closeOnOutsideClick: false,
    loadingVisible: false,
  };

  /** 消息框 */
  dialog: DxDialogInfo = {
    show: false,
    msg: "",
  };

  /**屏幕尺寸改变 */
  screenSizeChanged() {
    this.screen.getScreenSizeInfo = this.getScreenSizeInfo();
  }

  /**
   * 显示loading框
   * @param show 是否显示
   */
  showLoadingOfApp(show: boolean) {
    this.loadPanelInfo.loadingVisible = show;
  }

  /**
   * 显示消息框8
   * @param msg 消息框内容
   */
  showErrorDialog(msg) {
    this.dialog.show = true;
    this.dialog.msg = msg;
    notify(msg, "error");
  }

  @Provide()
  themeSwitch: ThemeSwitch = new ThemeSwitch();
  AppIsInited = false;

  @Provide()
  apiTool: ApiTool = new ApiTool();

  @Provide()
  menu: Menu = new Menu();

  @Provide()
  auth: Auth = new Auth();
  @Provide()
  rightContextOption: RightContextI = {
    content: null,
    items: [
      {
        text: "刷新",
        id: "refresh",
      },
    ],
  };
  defaultRightContextOption: RightContextI = {
    content: null,
    items: [
      {
        text: "刷新",
        id: "refresh",
      },
    ],
  };
  mounted() {
    subscribe(this.screenSizeChanged);
    // 刷新token方法
    let refreshToken = (refresh: string) => {
      let client = this.apiTool.createAuthClient(authClient);
      let form: AuthInfoI = {
        ...authOptions,
        grant_type: "refresh_token",
        refresh_token: refresh,
      };
      return client
        .login(form)
        .then((result) => {
          let token = result["access_token"];
          Auth.saveToken(token);
          Auth.saveUser(result);
          return token;
        })
        .catch(() => {
          return null;
        });
    };
    // 初始化刷新token
    this.auth.initRefreshToken(refreshToken);
    this.$router.beforeEach(async (to, from, next) => {
      let isLogin = await this.auth.isLogin();
      if (!isLogin) {
        // 未登录
        if (to.path == LOGINPATH) {
          next();
        } else {
          next(LOGINPATH);
        }
      }
      // 已登录
      else {
        if (to.path == LOGINPATH) {
          next("/");
        } else {
          next();
        }
      }
    });
  }

  async created() {
    loadMessages(zhMessages);
    locale(navigator.language);
    this.AppIsInited = false;
    setTimeout(() => {
      this.AppIsInited = true;
    }, 3000);
    await this.themeSwitch.switch(this.themeSwitch.themeList[1].id);
    this.AppIsInited = true;
  }

  beforeUnmount() {
    unsubscribe(this.screenSizeChanged);
  }

  getScreenSizeInfo() {
    const screenSizes = sizes();
    return {
      isXSmall: screenSizes["screen-x-small"],
      isLarge: screenSizes["screen-large"],
      cssClasses: Object.keys(screenSizes).filter((cl) => screenSizes[cl]),
    };
  }
}
</script>

<style lang="scss">
@import "http://at.alicdn.com/t/font_1096724_qoxr99r04y.css";
@import "./app.scss";
</style>

